package com.lhc.web.controller;

import com.alibaba.fastjson.JSON;
import com.lhc.web.Entity.UserEntity;
import org.apache.http.HttpHost;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author lhc
 * @Date 2021/8/2 9:04
 */
@RestController
@RequestMapping("/es/user")
public class UserController {

    //索引库名字
    private static final String user_db_name = "user_db";

    //客户端连接
    private RestHighLevelClient restHighLevelClient;

    public UserController() {
        RestClientBuilder restClientBuilder = RestClient.builder(
                new HttpHost("localhost", 9200, "http"),
                new HttpHost("192.168.61.143", 9200, "http")
        );
        restHighLevelClient = new RestHighLevelClient(restClientBuilder);
    }

    /**
     * 添加文档(行记录)
     */
    @PostMapping("/add")
    public void add(@RequestBody UserEntity userEntity) throws IOException {
        //1.构建IndexRequest对象
        IndexRequest indexRequest = new IndexRequest(user_db_name);
        //2.设置文档id  这个id不是用户属性里面的id
        indexRequest.id(String.valueOf(userEntity.getId()));
        //3。设置文档数据，并设置请求的数据为json格式
        String json = JSON.toJSONString(userEntity);
        indexRequest.source(json, XContentType.JSON);
        //4.发起请求添加数据到user索引库
        restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
    }

    /**
     * 更新文档(行记录)
     */
    @PostMapping("/update")
    public void update(@RequestBody UserEntity userEntity) throws IOException {
        //1.判断对应的id文档是否存储
        GetRequest getRequest = new GetRequest(user_db_name, String.valueOf(userEntity.getId()));
        boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
        if (exists) {
            //2.构建updateRequest对象
            UpdateRequest updateRequest = new UpdateRequest(user_db_name, String.valueOf(userEntity.getId()));
            //3.设置构建updateRequest对象的文档
            updateRequest = updateRequest.doc(JSON.toJSONString(userEntity), XContentType.JSON);
            restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
        }

    }

    /**
     * 查询所有文档（查询记录）
     */
    @GetMapping("/findAll")
    public List<UserEntity> findAll(@RequestParam String dbName) throws IOException {
        List<UserEntity> userEntities = new ArrayList<>();

        //1.构建IndexRequest对象
        SearchRequest searchRequest = new SearchRequest(dbName);
        //2.发送请求
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //3.解析返回对象
        SearchHits searchHit = searchResponse.getInternalResponse().hits();
        //总条数
        TotalHits totalHits = searchHit.getTotalHits();
        System.out.println("总条数：" + totalHits.value);
        //记录
        SearchHit[] hits = searchHit.getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            UserEntity userEntity = JSON.parseObject(sourceAsString, UserEntity.class);
            System.out.println(userEntity);
            userEntities.add(userEntity);
        }
        return userEntities;
    }

    /**
     * 根据id查询
     */
    @GetMapping("/getById/{id}")
    public UserEntity getById(@PathVariable(value = "id") String id) throws IOException {
        //1.构建IndexRequest对象
        GetRequest getRequest = new GetRequest(user_db_name, id);
        //2.发送请求
        GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
        //3.解析返回对象
        String sourceAsString = getResponse.getSourceAsString();
        UserEntity userEntity = JSON.parseObject(sourceAsString, UserEntity.class);
        System.out.println(userEntity);
        return userEntity;
    }

    /**
     * 删除
     */
    @DeleteMapping("/deleteById/{id}")
    public void deleteById(@PathVariable(value = "id") String id) throws IOException {
        //1.构建IndexRequest对象
        DeleteRequest getRequest = new DeleteRequest(user_db_name, id);
        //2.发送请求
        restHighLevelClient.delete(getRequest, RequestOptions.DEFAULT);
    }

    /**
     * 根据条件查询
     */
    @GetMapping("/find")
    public List<UserEntity> find(UserEntity userEntity) throws IOException {
        List<UserEntity> userEntities = new ArrayList<>();

        //1.构建请求对象
        SearchRequest searchRequest = buildUserSearchRequest(userEntity);
        //2.发送请求
        SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        //3.解析
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            UserEntity userEntity2 = JSON.parseObject(sourceAsString, UserEntity.class);
            userEntities.add(userEntity2);
        }
        return userEntities;
    }


    /**
     * 构建es检索对象
     *
     * @return 前端请求参数
     */
    private SearchRequest buildUserSearchRequest(UserEntity userEntity) {
        //封装查询的DSL相关信息  1.query、2.排序、3.分页、4.高亮 5、聚合 6.nsted
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //1。query
        BoolQueryBuilder boolQueryBuilder = this.buildUserBoolQueryBuilder(userEntity);
        searchSourceBuilder.query(boolQueryBuilder);


        System.out.println("构建的DSL语句 {}:" + searchSourceBuilder.toString());
        return new SearchRequest(new String[]{user_db_name}, searchSourceBuilder);
    }

    /**
     * 构建BoolQueryBuilder
     *
     * @param userEntity 请求对象
     * @return BoolQueryBuilder
     */
    private BoolQueryBuilder buildUserBoolQueryBuilder(UserEntity userEntity) {
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        if (!StringUtils.isEmpty(userEntity.getName())) {
            boolQueryBuilder.must(QueryBuilders.matchQuery("name", userEntity.getName()));
        }
        if (!StringUtils.isEmpty(userEntity.getAge())) {
            boolQueryBuilder.must(QueryBuilders.termQuery("age", userEntity.getAge()));
        }
        if (!StringUtils.isEmpty(userEntity.getAdd())) {
            //单字段查询
            boolQueryBuilder.must(QueryBuilders.matchQuery("add", userEntity.getAdd()));
            //多字段查询
            //boolQueryBuilder.must(QueryBuilders.multiMatchQuery(requestParamDTO.getKeyword(), "name", "keywords", "subTitle"));
        }
        if (!StringUtils.isEmpty(userEntity.getPhone())) {
            //单字段查询
            boolQueryBuilder.must(QueryBuilders.matchQuery("phone", userEntity.getPhone()));
        }
        return boolQueryBuilder;
    }
}